package br.com.android.aluno.dao;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import br.com.android.aluno.enums.Sexo;
import br.com.android.aluno.model.Aluno;

public class AlunoDao {

	// Dados do banco de dados
	protected static String TABELA = "aluno";
	
	// Colunas
	protected static final String COLUNA_ID = "id";
	protected static final String COLUNA_NOME = "nome";
	protected static final String COLUNA_TELEFONE = "telefone";
	protected static final String COLUNA_EMAIL = "email";
	protected static final String COLUNA_ENDERECO = "endereco";
	protected static final String COLUNA_CURSO = "curso";
	protected static final String COLUNA_FOTOPATH = "foto_path";
	protected static final String COLUNA_SEXO = "sexo";
	protected static final String COLUNA_MATRICULADO = "matriculado";
	
	// LogCat para o banco de dados
	private static final String LOG_BD = "bd";
	
	// Array de colunas
	private static String COLUNAS[] = { COLUNA_ID, COLUNA_NOME,
			COLUNA_TELEFONE, COLUNA_EMAIL, COLUNA_ENDERECO, COLUNA_CURSO,
			COLUNA_FOTOPATH, COLUNA_SEXO, COLUNA_MATRICULADO };
	
	private static SQLiteDatabase db = null;
		
	public AlunoDao(Context context) {		
		// Abre um conexao com o Banco de Dados
		if(db == null){
			db = context.openOrCreateDatabase(DaoFactory.NOME_BANCO, Context.MODE_PRIVATE,
					null);
		}
	}
	
	public long salvar(Aluno aluno){
		long id = aluno.getId();
		
		if(id == 0){
			id = inserir(aluno);
		} else{
			id = atualizar(aluno);
		}
		
		return id;
	}

	/**
	 * Insere uma entidade no banco de dados.
	 * 
	 * SQL: inser into aluno values...
	 * 
	 * @param aluno
	 * @return ID
	 */
	public long inserir(Aluno aluno){
		ContentValues values = new ContentValues();
		values.put(COLUNA_NOME, aluno.getNome());
		values.put(COLUNA_TELEFONE, aluno.getTelefone());
		values.put(COLUNA_EMAIL, aluno.getEmail());
		values.put(COLUNA_ENDERECO, aluno.getEndereco());
		values.put(COLUNA_CURSO, aluno.getCurso());
		values.put(COLUNA_FOTOPATH, aluno.getFotoPath() != null ? aluno.getFotoPath().getAbsolutePath() : "");
		values.put(COLUNA_SEXO, Sexo.getCode(aluno.getSexo()));
		values.put(COLUNA_MATRICULADO, aluno.isMatriculado() ? 1 : 0);
		
		long saida = inserir(values);
		return saida;
	}

	private long inserir(ContentValues values) {
		long id = getDB().insert(TABELA, null, values);
		Log.i(LOG_BD, "Salvou o registro [" + id + "].");
		
		return id;
	}

	/**
	 * Atualiza a entidade no banco. o id da entidade eh utilizado.
	 * 
	 * SQL: update aluno set nome = ?, telefone = ?, ... where id = ID_ALUNO; 
	 * 
	 * @param aluno
	 * @return cont
	 */
	public int atualizar(Aluno aluno){
		ContentValues values = new ContentValues();
		values.put(COLUNA_ID, aluno.getId());
		values.put(COLUNA_NOME, aluno.getNome());
		values.put(COLUNA_TELEFONE, aluno.getTelefone());
		values.put(COLUNA_EMAIL, aluno.getEmail());
		values.put(COLUNA_ENDERECO, aluno.getEndereco());
		values.put(COLUNA_CURSO, aluno.getCurso());
		values.put(COLUNA_FOTOPATH, aluno.getFotoPath() != null ? aluno.getFotoPath().getAbsolutePath() : "");
		values.put(COLUNA_SEXO, Sexo.getCode(aluno.getSexo()));
		values.put(COLUNA_MATRICULADO, aluno.isMatriculado() ? 1 : 0);
		
		String id = String.valueOf(aluno.getId());
		String where = COLUNA_ID + "=?";
		String[] whereArgs = new String[] { id };

		int cont = atualizar(values, where, whereArgs);
		return cont;
	}

	/**
	 * Atualiza a entidade com os valores abaixo
	 * 
	 * @param values
	 * @param where
	 * @param whereArgs
	 * @return
	 */
	private int atualizar(ContentValues values, String where, String[] whereArgs) {
		int cont = getDB().update(TABELA, values, where, whereArgs);
		Log.i(LOG_BD, "Atualizou [" + cont + "] registros.");
				
		return cont;
	}
	
	/**
	 * Deleta a entidade com o id fornecido.
	 * 
	 * SQL: delete from aluno where id = ID;
	 * 
	 * @param id
	 * @return
	 */
	public int deletar(long id) {
		String where = COLUNA_ID + "=?";
		String[] whereArgs = new String[] { String.valueOf(id) };

		int cont = deletar(where, whereArgs);
		return cont;
	}

	/**
	 * Deleta a entidade com os argumentos fornecidos.
	 * 
	 * @param where
	 * @param whereArgs
	 * @return
	 */
	private int deletar(String where, String[] whereArgs) {
		int cont = getDB().delete(TABELA, where, whereArgs);
		Log.i(LOG_BD, "Deletou [" + cont + "] registros.");
				
		return cont;
	}
	
	/**
	 * Faz uma consulta pelo id do aluno
	 * select * from aluno where id = ID_ALUNO;
	 * @param id
	 * 
	 * @return Aluno
	 */
	public Aluno buscar(long id){
		Cursor c = getDB().query(TABELA, COLUNAS, 
				COLUNA_ID + " = " + id, null, null, null, null);
		
		Aluno aluno = null;
		
		if(c.getCount() > 0){
			aluno = new Aluno();
			c.moveToFirst();
			
			aluno.setId(c.getInt(c.getColumnIndex(COLUNA_ID)));
			aluno.setNome(c.getString(c.getColumnIndex(COLUNA_NOME)));
			aluno.setTelefone(c.getString(c.getColumnIndex(COLUNA_TELEFONE)));
			aluno.setEmail(c.getString(c.getColumnIndex(COLUNA_EMAIL)));
			aluno.setEndereco(c.getString(c.getColumnIndex(COLUNA_ENDERECO)));
			aluno.setCurso(c.getString(c.getColumnIndex(COLUNA_CURSO)));
			aluno.setFotoPath(c.getString(c.getColumnIndex(COLUNA_FOTOPATH)).equals("") ? null : new File(c.getString(c.getColumnIndex(COLUNA_FOTOPATH))));
			aluno.setSexo(Sexo.getSexoByCode(c.getInt((c.getColumnIndex(COLUNA_SEXO)))));
			aluno.setMatriculado(c.getInt(c.getColumnIndex(COLUNA_MATRICULADO)) == 1 ? true : false);
			
			c.close();
		}
				
		return aluno;
	}
	
	/**
	 * Faz uma consulta pelo nome do aluno
	 * select * from aluno where id = NOME_ALUNO;
	 * @param nome
	 * 
	 * @return Aluno
	 */
	public Aluno buscar(String nome){
		Cursor c = getDB().query(TABELA, COLUNAS, 
				COLUNA_NOME + " = ?", new String[]{nome}, null, null, null);
		
		Aluno aluno = null;
		
		if(c.getCount() > 0){
			aluno = new Aluno();
			c.moveToFirst();
			
			aluno.setId(c.getInt(c.getColumnIndex(COLUNA_ID)));
			aluno.setNome(c.getString(c.getColumnIndex(COLUNA_NOME)));
			aluno.setTelefone(c.getString(c.getColumnIndex(COLUNA_TELEFONE)));
			aluno.setEmail(c.getString(c.getColumnIndex(COLUNA_EMAIL)));
			aluno.setEndereco(c.getString(c.getColumnIndex(COLUNA_ENDERECO)));
			aluno.setCurso(c.getString(c.getColumnIndex(COLUNA_CURSO)));
			aluno.setFotoPath(c.getString(c.getColumnIndex(COLUNA_FOTOPATH)).equals("") ? null : new File(c.getString(c.getColumnIndex(COLUNA_FOTOPATH))));
			aluno.setSexo(Sexo.getSexoByCode(c.getInt((c.getColumnIndex(COLUNA_SEXO)))));
			aluno.setMatriculado(c.getInt(c.getColumnIndex(COLUNA_MATRICULADO)) == 1 ? true : false);
			
			c.close();
		}
		
		return aluno;
	}
	
	/**
	 * Lista todos os alunos do banco
	 * select * from aluno
	 * 
	 * @return List<Aluno>
	 * 
	 */
	public List<Aluno> listar(){
		return listar(getCursor());
	}
	
	private List<Aluno> listar(Cursor c){
		List<Aluno> alunos = null;
		Aluno aluno = null;
		
		if(c != null){
			alunos = new ArrayList<Aluno>();
			
			if(c.moveToFirst()){
				do{
					aluno = new Aluno();
					
					aluno.setId(c.getInt(c.getColumnIndex(COLUNA_ID)));
					aluno.setNome(c.getString(c.getColumnIndex(COLUNA_NOME)));
					aluno.setTelefone(c.getString(c.getColumnIndex(COLUNA_TELEFONE)));
					aluno.setEmail(c.getString(c.getColumnIndex(COLUNA_EMAIL)));
					aluno.setEndereco(c.getString(c.getColumnIndex(COLUNA_ENDERECO)));
					aluno.setCurso(c.getString(c.getColumnIndex(COLUNA_CURSO)));
					aluno.setFotoPath(c.getString(c.getColumnIndex(COLUNA_FOTOPATH)).equals("") ? null : new File(c.getString(c.getColumnIndex(COLUNA_FOTOPATH))));
					aluno.setSexo(Sexo.getSexoByCode(c.getInt((c.getColumnIndex(COLUNA_SEXO)))));
					aluno.setMatriculado(c.getInt(c.getColumnIndex(COLUNA_MATRICULADO)) == 1 ? true : false);
					
					alunos.add(aluno);
					
				} while(c.moveToNext());
				
				c.close();
			}
		}
		
		return alunos;
	}

	/**
	 * Retorna um cursor com todos os alunos.
	 * select * from aluno
	 * @return cursor
	 */
	public Cursor getCursor() {
		try {
			return getDB().query(TABELA, COLUNAS, 
					null, null, null, null, null, null);
		} catch (Exception e) {
			Log.e(LOG_BD, "Erro ao buscar alunos: " + e.getMessage(), e);
			fechar();
			return null;
		}		
	}
	
	private SQLiteDatabase getDB() {
		return db;
	}

	/**
	 * Fecha a conexao com o banco.
	 */
	public void fechar() {
		if (db != null) {
			db.close();
		}
	}
}
